home *** CD-ROM | disk | FTP | other *** search
- <?xml version="1.0"?>
-
- <!-- ***** BEGIN LICENSE BLOCK *****
- - Version: MPL 1.1/GPL 2.0/LGPL 2.1
- -
- - The contents of this file are subject to the Mozilla Public License Version
- - 1.1 (the "License"); you may not use this file except in compliance with
- - the License. You may obtain a copy of the License at
- - http://www.mozilla.org/MPL/
- -
- - Software distributed under the License is distributed on an "AS IS" basis,
- - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- - for the specific language governing rights and limitations under the
- - License.
- -
- - The Original Code is Filter Action Rules.
- -
- - The Initial Developer of the Original Code is
- - Scott MacGregor <mscott@mozilla.org>.
- - Portions created by the Initial Developer are Copyright (C) 2005
- - the Initial Developer. All Rights Reserved.
- -
- - Contributor(s):
- -
- - Alternatively, the contents of this file may be used under the terms of
- - either the GNU General Public License Version 2 or later (the "GPL"), or
- - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- - in which case the provisions of the GPL or the LGPL are applicable instead
- - of those above. If you wish to allow use of your version of this file only
- - under the terms of either the GPL or the LGPL, and not to allow others to
- - use your version of this file under the terms of the MPL, indicate your
- - decision by deleting the provisions above and replace them with the notice
- - and other provisions required by the LGPL or the GPL. If you do not delete
- - the provisions above, a recipient may use your version of this file under
- - the terms of any one of the MPL, the GPL or the LGPL.
- -
- - ***** END LICENSE BLOCK ***** -->
-
- <!--
- This file has the following external dependencies:
- -gFilterActionStrings from FilterEditor.js
- -gFilterList from FilterEditor.js
- -gPromptService from FilterEditor.js
- -gMessengerBundle from msgFolderPickerOverlay.js
- -GetMsgFolderFromUri, SetFolderPickerElement from msgFolderPickerOverlay.js
- -->
-
- <!DOCTYPE dialog [
- <!ENTITY % filterEditorDTD SYSTEM "chrome://messenger/locale/FilterEditor.dtd" >
- %filterEditorDTD;
- <!ENTITY % msgFolderPickerOverlayDTD SYSTEM "chrome://messenger/locale/msgFolderPickerOverlay.dtd" >
- %msgFolderPickerOverlayDTD;
- ]>
-
- <bindings id="filterBindings"
- xmlns="http://www.mozilla.org/xbl"
- xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
- xmlns:nc="http://home.netscape.com/NC-rdf#"
- xmlns:xbl="http://www.mozilla.org/xbl">
-
- <binding id="ruleactiontype-menulist">
- <content>
- <xul:menulist class="ruleaction-type">
- <xul:menupopup>
- <xul:menuitem label="&moveMessage.label;" value="movemessage" enablefornews="false"/>
- <xul:menuitem label="©Message.label;" value="copymessage"/>
- <xul:menuseparator enablefornews="false"/>
- <xul:menuitem label="&forwardTo.label;" value="forwardmessage" enablefornews="false"/>
- <xul:menuitem label="&replyWithTemplate.label;" value="replytomessage" enablefornews="false"/>
- <xul:menuseparator/>
- <xul:menuitem label="&markMessageRead.label;" value="markasread"/>
- <xul:menuitem label="&markMessageFlagged.label;" value="markasflagged"/>
- <xul:menuitem label="&labelMessage.label;" value="labelmessageas"/>
- <xul:menuitem label="&setPriority.label;" value="setpriorityto"/>
- <xul:menuitem label="&setJunkScore.label;" value="setjunkscore" enablefornews="false"/>
- <xul:menuseparator enableforpop3="true"/>
- <xul:menuitem label="&deleteMessage.label;" value="deletemessage"/>
- <xul:menuitem label="&deleteFromPOP.label;" value="deletefrompopserver" enableforpop3="true"/>
- <xul:menuitem label="&fetchFromPOP.label;" value="fetchfrompopserver" enableforpop3="true"/>
- <xul:menuseparator enablefornews="true"/>
- <xul:menuitem label="&ignoreThread.label;" value="ignorethread" enablefornews="true"/>
- <xul:menuitem label="&watchThread.label;" value="watchthread" enablefornews="true"/>
- </xul:menupopup>
- </xul:menulist>
- </content>
-
- <implementation>
- <constructor>
- <![CDATA[
- this.hideInvalidActions();
- // differentiate between creating a new, next available action,
- // and creating a row which will be initialized with an action
- if (!this.parentNode.hasAttribute('initialActionIndex'))
- {
- var unavailableActions = this.usedActionsList();
- // select the first one that's not in the list
- var menuItems = this.menupopup.getElementsByTagName('menuitem');
- for (var index = 0; index < menuItems.length; index++)
- {
- var menu = menuItems[index];
- if (!(menu.value in unavailableActions) && !menu.hidden)
- {
- this.menulist.value = menu.value;
- this.parentNode.setAttribute('value', menu.value);
- break;
- }
- }
- }
- else
- {
- this.parentNode.mActionTypeInitialized = true;
- this.parentNode.clearInitialActionIndex();
- }
- ]]>
- </constructor>
-
- <field name="menupopup">document.getAnonymousNodes(this)[0].menupopup</field>
- <field name="menulist">document.getAnonymousNodes(this)[0]</field>
-
- <method name="hideInvalidActions">
- <body>
- <![CDATA[
- var scope = getScopeFromFilterList(gFilterList);
-
- // walk through the list of filter actions and hide any actions which aren't valid
- // for our given scope (news, imap, pop, etc)
- var elements, i;
-
- // disable / enable all elements in the "filteractionlist"
- // based on the scope and the "enablefornews" attribute
- elements = this.menupopup.getElementsByAttribute("enablefornews", "true");
- for (i = 0; i < elements.length; i++)
- elements[i].hidden = scope != Components.interfaces.nsMsgSearchScope.newsFilter;
-
- elements = this.menupopup.getElementsByAttribute("enablefornews", "false");
- for (i = 0; i < elements.length; i++)
- elements[i].hidden = scope == Components.interfaces.nsMsgSearchScope.newsFilter;
-
- elements = this.menupopup.getElementsByAttribute("enableforpop3", "true");
- for (i = 0; i < elements.length; i++)
- elements[i].hidden = scope != Components.interfaces.nsMsgSearchScope.offlineMailFilter;
- ]]>
- </body>
- </method>
-
- <method name="numVisibleActions">
- <body>
- <![CDATA[
- var numVisibleActions = 0;
- var menuItems = this.menupopup.getElementsByTagName('menuitem');
- // only count the items that are visible
- for (var index = 0; index < menuItems.length; index++)
- if (!menuItems[index].hidden)
- numVisibleActions++;
- return numVisibleActions;
- ]]>
- </body>
- </method>
-
- <!-- returns a hash containing all of the filter actions which are currently being used by other filteractionrows -->
- <method name="usedActionsList">
- <body>
- <![CDATA[
- var usedActions = {};
- var currentFilterActionRow = this.parentNode;
- var listBox = currentFilterActionRow.mListBox; // need to account for the list item
- // now iterate over each list item in the list box
- for (var index = 0; index < listBox.getRowCount(); index++)
- {
- var filterActionRow = listBox.getItemAtIndex(index);
- if (filterActionRow != currentFilterActionRow)
- usedActions[filterActionRow.getAttribute('value')] = true;
- }
- return usedActions;
- ]]>
- </body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="command">
- <![CDATA[
- this.parentNode.setAttribute('value', this.menulist.value);
- ]]>
- </handler>
-
- <handler event="popupshowing">
- <![CDATA[
- var unavailableActions = this.usedActionsList();
- var menuItems = this.menupopup.getElementsByTagName('menuitem');
- for (var index = 0; index < menuItems.length; index++)
- {
- var menu = menuItems[index];
- menu.setAttribute('disabled', menu.value in unavailableActions);
- }
- ]]>
- </handler>
- </handlers>
- </binding>
-
- <binding id="ruleaction">
- <content allowevents="true">
- <xul:listcell class="ruleactiontype"/>
- <xul:listcell class="ruleactiontarget" xbl:inherits="type=value"
- orient="vertical" align="start" pack="center"/>
- <xul:listcell>
- <xul:button class="small-button" label="+" onclick="this.parentNode.parentNode.addRow();"/>
- <xul:button class="small-button" label="-" onclick="this.parentNode.parentNode.removeRow();" anonid="removeButton"/>
- </xul:listcell>
- <xul:listcell/>
- </content>
-
- <implementation>
- <field name="mListBox">this.parentNode</field>
- <field name="mRemoveButton">document.getAnonymousElementByAttribute(this, "anonid", "removeButton")</field>
- <field name="mActionTypeInitialized">false</field>
- <field name="mRuleActionTargetInitialized">false</field>
-
- <method name="clearInitialActionIndex">
- <body>
- <![CDATA[
- // we should only remove the initialActionIndex after we have been told that
- // both the rule action type and the rule action target hvae both been built since they both need
- // this piece of information. This complication arises because both of these child elements are getting
- // bound asynchronously after the search row has been constructed
-
- if (this.mActionTypeInitialized && this.mRuleActionTargetInitialized)
- this.removeAttribute('initialActionIndex');
- ]]>
- </body>
- </method>
-
- <method name="initWithAction">
- <parameter name="aFilterAction"/>
- <body>
- <![CDATA[
- var filterActionStr = gFilterActionStrings[aFilterAction.type];
- document.getAnonymousNodes(document.getAnonymousNodes(this)[0])[0].value = filterActionStr;
- var actionTarget = document.getAnonymousNodes(this)[1];
- switch (gFilterActionStrings[aFilterAction.type])
- {
- case "movemessage":
- case "copymessage":
- gPicker = actionTarget;
- SetFolderPickerElement(aFilterAction.targetFolderUri, actionTarget.menulist);
- break;
- case "replytomessage":
- case "forwardmessage":
- document.getAnonymousNodes(actionTarget)[0].value = aFilterAction.strValue;
- break;
- case "labelmessageas":
- document.getAnonymousNodes(actionTarget)[0].value = aFilterAction.label;
- break;
- case "setpriorityto":
- document.getAnonymousNodes(actionTarget)[0].value = aFilterAction.priority;
- break;
- case "setjunkscore":
- document.getAnonymousNodes(actionTarget)[0].value = aFilterAction.junkScore;
- break;
- default:
- break;
- }
-
- this.mRuleActionTargetInitialized = true;
- this.clearInitialActionIndex();
- ]]>
- </body>
- </method>
-
- <method name="validateAction">
- <body>
- <![CDATA[
- // returns true if this row represents a valid filter action and false otherwise.
- // This routine also prompts the user.
- var filterActionString = this.getAttribute('value');
- var actionTarget = document.getAnonymousNodes(this)[1];
- var errorString;
-
- switch (filterActionString)
- {
- case "movemessage":
- case "copymessage":
- var msgFolder = actionTarget.uri ? GetMsgFolderFromUri(actionTarget.uri) : null;
- if (!msgFolder || !msgFolder.canFileMessages)
- errorString = "mustSelectFolder";
- break;
- case "forwardmessage":
- if (document.getAnonymousNodes(actionTarget)[0].value.length < 3 ||
- document.getAnonymousNodes(actionTarget)[0].value.indexOf('@') < 2)
- errorString = "enterValidEmailAddress";
- break;
- case "replytomessage":
- if (!document.getAnonymousNodes(actionTarget)[0].selectedItem)
- errorString = "pickTemplateToReplyWith";
- break;
- default:
- break;
- }
-
- if (errorString && gPromptService)
- gPromptService.alert(window, null, gFilterBundle.getString(errorString));
-
- return !errorString;
- ]]>
- </body>
- </method>
-
- <method name="saveToFilter">
- <parameter name="aFilter"/>
- <body>
- <![CDATA[
- // create a new filter action, fill it in, and then append it to the filter
- var filterAction = aFilter.createAction();
- var filterActionString = this.getAttribute('value');
- filterAction.type = gFilterActionStrings.indexOf(filterActionString);
- var actionTarget = document.getAnonymousNodes(this)[1];
-
- switch (filterActionString)
- {
- case "labelmessageas":
- filterAction.label = document.getAnonymousNodes(actionTarget)[0].getAttribute("value");
- break;
- case "setpriorityto":
- filterAction.priority = document.getAnonymousNodes(actionTarget)[0].getAttribute("value");
- break;
- case "movemessage":
- case "copymessage":
- filterAction.targetFolderUri = actionTarget.uri;
- break;
- case "setjunkscore":
- filterAction.junkScore = document.getAnonymousNodes(actionTarget)[0].value;
- break;
- case "replytomessage":
- case "forwardmessage":
- filterAction.strValue = document.getAnonymousNodes(actionTarget)[0].value;
- break;
- default:
- break;
- }
- aFilter.appendAction(filterAction);
- ]]>
- </body>
- </method>
-
- <method name="addRow">
- <body>
- <![CDATA[
- if (this.mListBox.getRowCount() < document.getAnonymousNodes(this)[0].numVisibleActions())
- {
- var listItem = document.createElement('listitem');
- listItem.className = 'ruleaction';
- this.mListBox.insertBefore(listItem, this.nextSibling);
- this.mListBox.ensureElementIsVisible(listItem);
-
- // make sure the first remove button is enabled
- this.mListBox.getItemAtIndex(0).mRemoveButton.disabled = false;
- }
- ]]>
- </body>
- </method>
-
- <method name="removeRow">
- <body>
- <![CDATA[
- if (this.mListBox.getRowCount() > 1)
- this.mListBox.removeChild(this);
- // if we only have one row left, then disable the remove button for that row
- this.mListBox.getItemAtIndex(0).mRemoveButton.disabled = this.mListBox.getRowCount() == 1;
- ]]>
- </body>
- </method>
- </implementation>
- </binding>
-
- <binding id="ruleactiontarget-base">
- <implementation>
- <constructor>
- <![CDATA[
- if (this.parentNode.hasAttribute('initialActionIndex'))
- {
- var actionIndex = this.parentNode.getAttribute('initialActionIndex');
- var filterAction = gFilter.actionList.QueryElementAt(actionIndex, Components.interfaces.nsIMsgRuleAction);
- this.parentNode.initWithAction(filterAction);
- }
- ]]>
- </constructor>
- </implementation>
- </binding>
-
- <binding id="ruleactiontarget-label" extends="chrome://messenger/content/searchWidgets.xml#ruleactiontarget-base">
- <content>
- <xul:menulist class="ruleactionitem">
- <xul:menupopup>
- <xul:menuitem value="0"/>
- <xul:menuitem value="1"/>
- <xul:menuitem value="2"/>
- <xul:menuitem value="3"/>
- <xul:menuitem value="4"/>
- <xul:menuitem value="5"/>
- </xul:menupopup>
- </xul:menulist>
- </content>
-
- <implementation>
- <constructor>
- <![CDATA[
- var menuItems = document.getAnonymousNodes(this)[0].menupopup.childNodes;
- var prefBranch = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService).getBranch(null);
-
- for (var index = 0; index < menuItems.length; index++)
- {
- var menuEl = menuItems[index];
- var prefString = prefBranch.getComplexValue("mailnews.labels.description." + menuEl.value,
- Components.interfaces.nsIPrefLocalizedString);
- menuEl.setAttribute("label", prefString);
- }
-
- // propagating a pre-existing hack to make the label get displayed correctly in the menulist
- // now that we've changed the labels for each menu list. We need to use the current selectedIndex
- // (if its defined) to handle the case where we were initialized with a filter action already.
- var currentItem = document.getAnonymousNodes(this)[0].selectedItem;
- document.getAnonymousNodes(this)[0].selectedItem = null;
- document.getAnonymousNodes(this)[0].selectedItem = currentItem;
- ]]>
- </constructor>
- </implementation>
- </binding>
-
- <binding id="ruleactiontarget-priority" extends="chrome://messenger/content/searchWidgets.xml#ruleactiontarget-base">
- <content>
- <xul:menulist class="ruleactionitem">
- <xul:menupopup>
- <xul:menuitem value="6" label="&highestPriorityCmd.label;"/>
- <xul:menuitem value="5" label="&highPriorityCmd.label;"/>
- <xul:menuitem value="4" label="&normalPriorityCmd.label;"/>
- <xul:menuitem value="3" label="&lowPriorityCmd.label;"/>
- <xul:menuitem value="2" label="&lowestPriorityCmd.label;"/>
- </xul:menupopup>
- </xul:menulist>
- </content>
- </binding>
-
- <binding id="ruleactiontarget-junkscore" extends="chrome://messenger/content/searchWidgets.xml#ruleactiontarget-base">
- <content>
- <xul:menulist class="ruleactionitem">
- <xul:menupopup>
- <xul:menuitem value="100" label="&junk.label;"/>
- <xul:menuitem value="0" label="¬Junk.label;"/>
- </xul:menupopup>
- </xul:menulist>
- </content>
- </binding>
-
- <binding id="ruleactiontarget-replyto" extends="chrome://messenger/content/searchWidgets.xml#ruleactiontarget-base">
- <content>
- <xul:menulist class="ruleactionitem">
- <xul:menupopup>
- </xul:menupopup>
- </xul:menulist>
- </content>
-
- <implementation>
- <constructor>
- <![CDATA[
- var accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Components.interfaces.nsIMsgAccountManager);
- var identity = accountManager.getFirstIdentityForServer(gFilterList.folder.server);
- var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
- var resource = rdfService.GetResource(identity.stationeryFolder);
- var msgFolder = resource.QueryInterface(Components.interfaces.nsIMsgFolder);
- var msgWindow = GetFilterEditorMsgWindow();
- var msgDatabase = msgFolder.getMsgDatabase(msgWindow);
- var enumerator = msgDatabase.EnumerateMessages();
- var templateListPopup = document.getAnonymousNodes(this)[0].menupopup;
-
- if ( enumerator )
- {
- while (enumerator.hasMoreElements())
- {
- var header = enumerator.getNext();
- if (header instanceof Components.interfaces.nsIMsgDBHdr)
- {
- var msgTemplateUri = msgFolder.URI + "?messageId=" + header.messageId + '&subject=' + header.subject;
- var newItem = document.getAnonymousNodes(this)[0].appendItem(header.subject, msgTemplateUri);
- }
- }
- }
- ]]>
- </constructor>
- </implementation>
- </binding>
-
- <binding id="ruleactiontarget-forwardto" extends="chrome://messenger/content/searchWidgets.xml#ruleactiontarget-base">
- <content>
- <xul:textbox class="ruleactionitem"/>
- </content>
- </binding>
-
- <binding id="ruleactiontarget-folder" extends="chrome://messenger/content/searchWidgets.xml#ruleactiontarget-base">
- <content>
- <xul:menulist class="ruleactionitem">
- <xul:menupopup class="folderTargetPopup" oncommand="SetFolderPickerElement(this.getAttribute('uri'), this.parentNode);"/>
- </xul:menulist>
- </content>
-
- <implementation>
-
- <constructor>
- <![CDATA[
- if (!this.uri)
- SetFolderPickerElement(this.menulist.firstChild.tree.builderView.getResourceAtIndex(0).Value, this.menulist);
- ]]>
- </constructor>
-
- <property name="uri" readonly="true" onget="return document.getAnonymousNodes(this)[0].getAttribute('uri');"/>
- <field name="menulist">document.getAnonymousNodes(this)[0]</field>
- </implementation>
- </binding>
- </bindings>
-